package com.ms.education.course.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ms.education.R;
import com.ms.education.constant.CourseConstant;
import com.ms.education.course.entity.*;
import com.ms.education.course.entity.vo.CourseResultVo;
import com.ms.education.course.entity.vo.PageCourseVo;
import com.ms.education.course.mapper.CourseMapper;
import com.ms.education.course.service.*;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 课程 服务实现类
 * </p>
 *
 * @author ms
 * @since 2023-01-17
 */
@Service
public class CourseServiceImp extends ServiceImpl<CourseMapper, Course> implements CourseService {

    @Autowired
    private ChapterService chapterService;

    @Autowired
    private CommentService commentService;

    @Autowired
    private CourseDescriptionService courseDescriptionService;

    @Autowired
    private CourseCollectService courseCollectService;

    @Override
    public Map<String, Object> pageCourse(PageCourseVo pageCourseVo, long current, long limit) {
        Page<Course> page = new Page<>(current, limit);
        String teacherName = pageCourseVo.getTeacherName();
        Integer teacherId = pageCourseVo.getTeacherId();
        Integer subjectId = pageCourseVo.getSubjectId();
        Integer subjectParentId = pageCourseVo.getSubjectParentId();
        String title = pageCourseVo.getTitle();
        Integer classId = pageCourseVo.getClassId();
        String status = pageCourseVo.getStatus();
        Date beginTime = pageCourseVo.getBeginTime();
        Date endTime = pageCourseVo.getEndTime();
        Boolean isContainComment = pageCourseVo.getIsContainComment();
        Boolean isContainChapter = pageCourseVo.getIsContainChapter();
        QueryWrapper<Course> wrapper = new QueryWrapper<>();
        if (!StringUtils.isEmpty(teacherName)) {
            wrapper.like("teacher_name", teacherName);
        }
        if (!StringUtils.isEmpty(subjectId)) {
            wrapper.eq("subject_id", subjectId);
        }
        if (!StringUtils.isEmpty(subjectParentId)) {
            wrapper.eq("subject_parent_id", subjectParentId);
        }
        if (!StringUtils.isEmpty(title)) {
            wrapper.like("title", title);
        }
        if (!StringUtils.isEmpty(classId)) {
            wrapper.eq("class_id", classId);
        } else {
            wrapper.isNull("class_id");
        }
        if (!StringUtils.isEmpty(status)) {
            wrapper.eq("status", status);
        }
        if (!StringUtils.isEmpty(beginTime)) {
            wrapper.ge("gmt_create", beginTime);
        }
        if (!StringUtils.isEmpty(endTime)) {
            wrapper.le("gmt_create", endTime);
        }
        if (!StringUtils.isEmpty(teacherId)) {
            wrapper.eq("teacher_id", teacherId);
        }
        if (pageCourseVo.getExcludes() != null && !pageCourseVo.getExcludes().isEmpty()) {
            wrapper.notIn("id", pageCourseVo.getExcludes());
        }
        wrapper.orderByDesc("gmt_modified");
        this.page(page, wrapper);
        long rows = page.getTotal();
        List<Course> courses = page.getRecords();
        List<Chapter> chapters = new LinkedList<>();
        List<Comment> comments = new LinkedList<>();
        List<Integer> courseIds = courses.stream().map(Course::getId).collect(Collectors.toList());
        //查询课程描述
        List<CourseDescription> courseDescriptions = new ArrayList<>();
        if (!courseIds.isEmpty()) {
            courseDescriptions = courseDescriptionService.list(new QueryWrapper<CourseDescription>().in("course_id", courseIds));
        }
        //查询课程章节
        if (!StringUtils.isEmpty(isContainChapter) && isContainChapter) {
            QueryWrapper<Chapter> wrapper1 = new QueryWrapper<>();
            wrapper1.in("course_id", courseIds).orderByAsc("sort");
            chapters = chapterService.list(wrapper1);
        }
        //查询课程评论
        if (!StringUtils.isEmpty(isContainComment) && isContainComment) {
            QueryWrapper<Comment> wrapper1 = new QueryWrapper<>();
            wrapper1.in("course_id", courseIds);
            wrapper1.orderByAsc("gmt_create");
            comments = commentService.list(wrapper1);
        }
        //封装数据
        List<Chapter> finalChapters = chapters;
        List<Comment> finalComments = comments;
        List<CourseDescription> finalCourseDescriptions = courseDescriptions;
        List<CourseResultVo> res = courses.stream().map(course -> {
            CourseResultVo resultVo = new CourseResultVo();
            BeanUtils.copyProperties(course, resultVo);
            List<Chapter> chapterList = new LinkedList<>();
            List<Comment> commentList = new LinkedList<>();
            finalCourseDescriptions.forEach(courseDescription -> {
                if (courseDescription.getCourseId() == course.getId()) {
                    resultVo.setDescription(courseDescription.getDescription());
                }
            });
            finalChapters.forEach(chapter -> {
                if (chapter.getCourseId() == course.getId())
                    chapterList.add(chapter);

            });
            finalComments.forEach(comment -> {
                if (comment.getCourseId() == course.getId())
                    commentList.add(comment);
            });
            resultVo.setChapters(chapterList);
            resultVo.setComments(commentList);
            return resultVo;
        }).collect(Collectors.toList());
        HashMap<String, Object> map = new HashMap<>();
        map.put("rows", rows);
        map.put("courses", res);
        return map;
    }

    @Override
    public R getCourseById(Integer id, Boolean isContainChapter, Boolean isContainComment) {
        Course course = this.getById(id);
        CourseResultVo res = new CourseResultVo();
        BeanUtils.copyProperties(course, res);
        if (!StringUtils.isEmpty(isContainChapter) && isContainChapter) {
            List<Chapter> chapters = chapterService.list(course.getId());
            res.setChapters(chapters);
        }
        if (!StringUtils.isEmpty(isContainComment) && isContainComment) {
            QueryWrapper<Comment> wrapper = new QueryWrapper<>();
            wrapper.eq("course_id", course.getId()).orderByAsc("gmt_create");
            List<Comment> comments = commentService.list(wrapper);
            res.setComments(comments);
        }
        //课程描述
        QueryWrapper<CourseDescription> wrapper = new QueryWrapper<>();
        wrapper.eq("course_id", id);
        CourseDescription courseDescription = courseDescriptionService.getOne(wrapper);
        res.setDescription(courseDescription.getDescription());
        return R.ok().data("course", res);
    }

    @Override
    @Transactional
    public R deleteCourseByIds(Integer[] ids) {
        QueryWrapper<Course> wrapper = new QueryWrapper<>();
        wrapper.in("id", ids).eq("status", CourseConstant.StatusEnum.STATUS_DRAFT.getStatus());
        List<Integer> idList = this.list(wrapper).stream().map(Course::getId).collect(Collectors.toList());
        R res = R.ok();
        if (idList.size() != ids.length) {
            res.message("索要删除的课程中有已发布的，只删除了未发布的");
        }
        this.removeBatchByIds(idList);
        if (!idList.isEmpty()) {
            //删除课程描述
            UpdateWrapper<CourseDescription> wrapper1 = new UpdateWrapper<>();
            wrapper1.in("course_id", idList);
            courseDescriptionService.remove(wrapper1);
            //删除课程章节
            chapterService.removeBatchByCourseIds(idList);
            //删除课程评论
            UpdateWrapper<Comment> wrapper2 = new UpdateWrapper<>();
            wrapper2.in("course_id", idList);
            commentService.remove(wrapper2);
        }
        return res;
    }

    @Transactional
    @Override
    public void saveOrUpdateCourse(Course course) {
        CourseDescription courseDescription = new CourseDescription();
        courseDescription.setDescription(course.getDescription());
        //添加
        if (StringUtils.isEmpty(course.getId())) {
            //保存课程基本信息
            this.save(course);
            //保存课程描述
            courseDescription.setCourseId(course.getId());
            courseDescriptionService.save(courseDescription);
        }
        //修改
        else {
            //更新课程基本信息
            this.updateById(course);
            //更新课程描述
            courseDescription.setCourseId(course.getId());
            UpdateWrapper<CourseDescription> wrapper = new UpdateWrapper<>();
            wrapper.eq("course_id", course.getId());
            courseDescriptionService.update(courseDescription, wrapper);
        }
    }

    @Override
    public Integer countCourseAdd(String day) {
        return baseMapper.countCourseAdd(day);
    }

    @Override
    public List<Course> index() {
        QueryWrapper<Course> wrapper = new QueryWrapper<>();
        wrapper.eq("status", CourseConstant.StatusEnum.STATUS_NORMAL.getStatus())
                .isNull("class_id")
                .orderByDesc("view_count")
                .last("limit 8");
        return list(wrapper);
    }

    @Override
    public List<Course> getTeacherCourses(Integer teacherId) {
        QueryWrapper<Course> wrapper = new QueryWrapper<>();
        wrapper.eq("teacher_id", teacherId)
                .eq("status", CourseConstant.StatusEnum.STATUS_NORMAL.getStatus())
                .orderByDesc("view_count");
        return list(wrapper);
    }

    @Override
    public Page<Course> pageCourseOfUser(long current, long limit, int userId) {
        QueryWrapper<CourseCollect> wrapper1 = new QueryWrapper<CourseCollect>()
                .eq("user_id", userId)
                .select("course_id");
        List<Integer> courseIds = courseCollectService.list(wrapper1).stream().map(CourseCollect::getCourseId).collect(Collectors.toList());
        Page<Course> page = new Page<>();
        if (!courseIds.isEmpty()) {
            QueryWrapper<Course> wrapper2 = new QueryWrapper<Course>()
                    .in("id", courseIds)
                    .eq("status", CourseConstant.StatusEnum.STATUS_NORMAL.getStatus());
            page.setCurrent(current).setSize(limit);
            page(page, wrapper2);
        }
        return page;
    }
}
